package com.example.demo.web

import com.example.demo.data.Order
import com.example.demo.data.User
import com.example.demo.data.repository.OrderRepository
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.data.domain.PageRequest
import org.springframework.security.core.Authentication
import org.springframework.security.core.annotation.AuthenticationPrincipal
import org.springframework.stereotype.Component
import org.springframework.stereotype.Controller
import org.springframework.ui.Model
import org.springframework.validation.Errors
import org.springframework.validation.annotation.Validated
import org.springframework.web.bind.annotation.*
import org.springframework.web.bind.support.SessionStatus
import javax.naming.AuthenticationException
import javax.validation.Valid
import javax.validation.constraints.Max
import javax.validation.constraints.Min

@Component
@ConfigurationProperties(prefix = "taco.orders")
@Validated
data class OrderProps(
        @Min(value = 5, message = "must be between 5 and 25")
        @Max(value = 25, message = "must be between 5 and 25")
        var pageSize: Int = 20
)

@Controller
@RequestMapping("/orders")
@SessionAttributes("order")
@ConfigurationProperties(prefix = "taco.orders")
class OrderController @Autowired constructor(
        private val orderRepo: OrderRepository,
        private val orderProps: OrderProps
) {

    @GetMapping("/current")
    fun orderForm(): String {
        return "orderForm"
    }

    @PostMapping
    fun processOrder(@Valid order: Order, error: Errors,
                     sessionStatus: SessionStatus,
                     @AuthenticationPrincipal user: User): String {
        if (error.hasErrors()) {
            return "orderForm"
        }

        order.user = user
        orderRepo.save(order)
        sessionStatus.setComplete()

        return "redirect:/"
    }

    @GetMapping
    fun orderForUser(@AuthenticationPrincipal user: User, model: Model): String {
        val pageable = PageRequest.of(0, orderProps.pageSize)
        model.addAttribute("orders", orderRepo.findByUserOrderByPlacedAtDesc(user, pageable))
        return "orderList"
    }
}